package com.szxy;

import com.alibaba.csp.sentinel.annotation.SentinelResource;
import com.alibaba.csp.sentinel.slots.block.BlockException;
import com.szxy.fail.BlockHandleConf;
import com.szxy.fail.RpcFallback;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.boot.SpringApplication;
import org.springframework.boot.autoconfigure.SpringBootApplication;
import org.springframework.cloud.client.discovery.EnableDiscoveryClient;
import org.springframework.cloud.client.loadbalancer.LoadBalanced;
import org.springframework.context.annotation.Bean;
import org.springframework.http.HttpStatus;
import org.springframework.http.ResponseEntity;
import org.springframework.web.bind.annotation.GetMapping;
import org.springframework.web.bind.annotation.PathVariable;
import org.springframework.web.bind.annotation.RestController;
import org.springframework.web.client.RestTemplate;

import java.util.HashMap;
import java.util.Map;

/**
 * @Author: zwz
 * @Date:2020/7/14 20:41
 * @Description:com.szxy
 * @Version:1.0
 **/
@SpringBootApplication
@EnableDiscoveryClient
@RestController
public class SentinelConsumerApplication2 {

    public static void main(String[] args) {
        SpringApplication.run(SentinelConsumerApplication2.class, args);
    }

    @LoadBalanced
    @Bean
    public RestTemplate getRestTemplate() {
        return new RestTemplate();
    }

    @Autowired
    private RestTemplate restTemplate;

    /**
     * 远程调用测试
     *
     * @return
     */
    @SentinelResource(value = "rpc", fallbackClass = RpcFallback.class, blockHandlerClass = BlockHandleConf.class, fallback = "rpcFallBack", blockHandler = "rpcHandler")
    @GetMapping("/rpc")
    public ResponseEntity<String> rpc(String type) {
        System.out.println("调用远程服务 rpc");

        // 模拟调用服务发生 java 异常
        if (null != type && type.equals("java")) {
            throw new RuntimeException("不想成功 ...");
        }
        ResponseEntity<String> result = this.restTemplate.getForEntity(
                "http://sentinel-provider/test",
                String.class
        );
        if (result.getStatusCode() == HttpStatus.OK) {
            return ResponseEntity.ok("远程调用 success");
        }
        throw new RuntimeException("远程调用失败 ...");
        // return ResponseEntity.badRequest().body("远程调用失败 ...");
    }

    /**
     * 调用服务 sentinel-provider
     * @param name
     * @param count
     * @return
     */
    @GetMapping("buy/{name}/{count}")
    @SentinelResource(value = "buy", fallback = "buyFallBack", blockHandler = "buyHandler")
    public ResponseEntity<String> buy(@PathVariable String name, @PathVariable Integer count) {
        if (count >= 20) {
            throw new IllegalArgumentException("购买数量过多");
        }
        if ("miband".equalsIgnoreCase(name)) {
            throw new NullPointerException("已售罄");
        }
        Map<String, Object> params = new HashMap<>(2);
        params.put("name", name);
        params.put("count", count);
        return ResponseEntity.ok(
                this.restTemplate.getForEntity("http://sentinel-provider/goods/buy/{name}/{count}"
                        , String.class, params).getBody());
    }


    /**
     * 服务降级
     * @param name
     * @param count
     * @return
     */
    public ResponseEntity buyFallBack(String name, Integer count, Throwable e) {
        return ResponseEntity.ok("异常名称： "+e+"===="+String.format("name= %s, count=%s", name, count));
    }

    /**
     * sentinel 回退
     * @param name
     * @param count
     * @param e
     * @return
     */
    public ResponseEntity buyHandler(String name, Integer count, Throwable e) {
        return ResponseEntity.ok("block ===异常名称： "+e+"===="+String.format("name= %s, count=%s", name, count));
    }




    /**
     * 服务降级
     * @param e
     * @return
     */
//    public ResponseEntity rpcFallBack(String type, Throwable e) {
//        return ResponseEntity.ok("异常类型为 "+type+",发生 java 异常, 异常信息为 ：" + e);
//    }

    /**
     * block 方法回退
     * @param type
     * @param e
     * @return
     */
//    public ResponseEntity rpcHandler(String type, BlockException e) {
//        return ResponseEntity.ok("异常类型为" + type + ",sentinel 规则错误, 错误信息为：" + e);
//    }
}
